<!DOCTYPE html>
<html>
  <head>
    <title>
      audit.js: basic tests
    </title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner({requireResultFile: true});


      // Basic assertion testing.
      audit.define(
          {
            label: 'basic',
            description: 'Simple unit tests for basic assertions.'
          },
          function(task, should) {
            should(OfflineAudioContext, 'OfflineAudioContext').exist();
            should(function() {
              let foo1 = 0;
            }, 'Setting foo1 to 0').notThrow();
            should(function() {
              let foo2 = bar;
            }).throw();
            should(function() {
              let foo3 = bar;
            }).throw(ReferenceError);
            should(function() {
              let foo4 = bar;
            }).throw(null);
            should(function() {
              let foo5 = bar;
            }).throw(undefined);
            should(() => {
              should();
            }, 'Calling should() with no argument').throw(Error);
            should(3 < 5, '3 < 5').beTrue();
            should(false).beFalse();
            should(1).beEqualTo(1)
            should(1).notBeEqualTo(2)
            should(NaN).beNaN();
            should(1).notBeNaN();
            should(typeof AudioContext.prototype).beEqualTo('object');
            should(2).beGreaterThan(1);
            should(2).beGreaterThanOrEqualTo(2);
            should(1).beLessThan(2);
            should(1).beLessThanOrEqualTo(1);
            should(should(1).beEqualTo(1), 'should(1).beEqualTo(1)').beTrue();
            should(true, 'The message is').message('truthful!', 'false!');

            should(BaseAudioContext.prototype, 'BaseAudioContext.prototype')
                .haveOwnProperty('createGain');
            should(BaseAudioContext.prototype, 'BaseAudioContext.prototype')
                .notHaveOwnProperty('startRendering');

            let ac = new AudioContext();
            let sourceNode = new AudioBufferSourceNode(ac);
            should(sourceNode, 'An AudioBufferSourceNode')
                .inheritFrom('AudioScheduledSourceNode');
            should(sourceNode, 'An AudioBufferSourceNode')
                .inheritFrom('AudioNode');

            let oac = new OfflineAudioContext(1, 128, 44100);
            Promise
                .all([
                  should(oac.startRendering(), 'Start OAC rendering')
                      .beResolved(),
                  should(
                      oac.decodeAudioData(),
                      'Decoding audio data with no argument')
                      .beRejected(),
                  should(oac.suspend(), 'Suspending OAC with no argument')
                      .beRejectedWith('TypeError')
                ])
                .then(task.done.bind(task));
          });


      // Advanced, mostly array-based numerical testing. Note that some codes
      // are commented out to avoid the trybot failure. These failures are
      // intentional, to demonstrate how the detailed failure report works.
      audit.define(
          {label: 'numerical', description: 'Numerical assertion unit test.'},
          function(task, should) {
            should(2.3).beCloseTo(2, {threshold: 0.3});
            should([1, 1, 1]).beConstantValueOf(1);
            should([1, 0, 1]).notBeConstantValueOf(1);
            should([1, 0, 0, 1]).notBeConstantValueOf(1);
            should([1, 1, 1]).beEqualToArray([1, 1, 1]);
            should([
              1, 1, 1, 1, 2, 2, 3, 3, 3
            ]).containValues([1, 2, 3], 'one, two, three');
            should([0.5, 0.5, 0.55, 0.5, 0.45, 0.5]).notGlitch(0.06);
            task.done();
          });

      audit.define(
          {
            label: 'numerical typed arrays',
            description: 'Numerical assertion unit test with typed arrays.'
          },
          function(task, should) {
            let testValues = [1, 2, 3];
            should(Uint8Array.from(testValues), 'Uint8Array')
                .beEqualToArray(testValues);
            should(Float32Array.from(testValues), 'Float32Array')
                .beEqualToArray(testValues);
            should(Float64Array.from(testValues), 'Float64Array')
                .beEqualToArray(testValues);
            task.done();
          });

      // Test Audit.loadFileFromUrl() within |should| assertion.
      // See: crbug.com/701813
      audit.define(
          {
            label: 'load-file-in-should',
            description:
                'Test Audit.loadFileFromUrl() within |should| assertion.'
          },
          (task, should) => {
            let url = '../resources/hyper-reality/laughter.wav';
            let promise = should(
                              Audit.loadFileFromUrl(url),
                              'Loading file within should().beResolved()')
                              .beResolved();
            promise.then(() => {task.done()});
          });


      // The task headline needs to be printed even if there is no description
      // is given.
      audit.define('dummy-label-string', function(task) {
        task.done();
      });


      // Test the same thing in a differen way.
      audit.define({label: 'dummy-label-object'}, function(task) {
        task.done();
      });


      // This task is defined, but you can selectively opt it out when the task
      // runs. If you would like to see how failure cases get printed, include
      // this task and launch the task runner.
      audit.define('empty', function(task, should) {
        task.done();
      });


      // You can enumerate tasks you want to execute in the order, or simply
      // pass no argument to run all the defined tasks.
      audit.run(
          'numerical', 'numerical typed arrays', 'basic', 'load-file-in-should',
          'dummy-label-string', 'dummy-label-object');
    </script>
  </body>
</html>
